﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSE.Deployment.ConfigurationManager.Controls;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using System.Windows.Media;

namespace PSEComponents.Deployment.ConfigurationManager.Controls.AuditLoggingServiceControl
{
    public abstract class ExtendedServiceControl : ServiceControl
    {
        private Label _partLabel;
        private StartStopButton _partButton;
        private Dictionary<string, BackgroundWorker> _productsWorkers;

        protected Dictionary<string, StartStopButton> ProductsControls
        {
            get;
            set;
        }

        private string _serviceName;

        public ExtendedServiceControl(PSE.Deployment.SetupBase.Configuration.WindowsService service)
            : base(service)
        {
            _serviceName = service.ServiceName;
            _productsWorkers = new Dictionary<string, BackgroundWorker>();
        }

        void _bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            bool hadErrors = (bool)e.Result;

            //recuperar o id do produto relacionao ao BackgroundWorker
            string productId = _productsWorkers.First(pw => pw.Value.GetHashCode() == sender.GetHashCode()).Key;

            StartStopButton button = this.ProductsControls[productId];

            if (!hadErrors)
            {
                //trocar o status do controls
                button.IsChecked = !button.IsChecked;
            }
            else
                ConfigurationMessageBox.Show(String.Format("Ocorreram erros ao tentar {0} a instância '{1}' do serviço. Verifique o conteúdo do event viewer para maiores detalhes.", button.IsChecked ? "parar" : "iniciar", productId), ConfigurationMessageBoxButton.Ok, ConfigurationMessageBoxImage.Error);

            button.IsProcessing = false;

        }

        void _bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            bool errorOccurred = false;
            try
            {
                List<object> objects = (List<object>)e.Argument;
                //recuperar o id do produto relacionao ao BackgroundWorker
                string product = _productsWorkers.First(pw => pw.Value.GetHashCode() == sender.GetHashCode()).Key;
                bool isChecked = (bool)objects[0];

                if (isChecked)
                    errorOccurred = !StopProduct(product);
                else
                    errorOccurred = !StartProduct(product);
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("PSEComponents - Configuration Manager", ex.ToString());
                errorOccurred = true;
            }

            e.Result = errorOccurred;
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _partLabel = base.GetTemplateChild("PART_ServiceName") as Label;
            _partButton = base.GetTemplateChild("PART_ToggleButton") as StartStopButton;

            ProductsControls = new Dictionary<string, StartStopButton>();

            List<string> allProducts = this.GetConfiguredProducts();

            if (allProducts != null && allProducts.Count > 0)
            {
                List<string> runningProducts = this.GetRunningProducts();
                StartStopButton button;
                Label label;
                Rectangle rectangle;
                Grid content = base.GetTemplateChild("PART_Content") as Grid;
                int row = 1;

                foreach (string productId in allProducts)
                {
                    //adicionar uma linha no grid
                    RowDefinition itemRow = new RowDefinition();
                    itemRow.Height = new GridLength(30, GridUnitType.Pixel);
                    content.RowDefinitions.Add(itemRow);

                    //criar retangulo
                    rectangle = new Rectangle();
                    rectangle.Name = "IconLevel2_" + row.ToString();
                    rectangle.HorizontalAlignment = HorizontalAlignment.Left;
                    rectangle.VerticalAlignment = VerticalAlignment.Center;
                    rectangle.Width = Convert.ToDouble(4);
                    rectangle.Height = Convert.ToDouble(4);
                    rectangle.Margin = new Thickness(20, -5, 0, 0);
                    rectangle.Fill = new SolidColorBrush(Color.FromArgb(255, 92, 105, 117));
                    rectangle.Stretch = Stretch.Fill;
                    Grid.SetColumn(rectangle, 0);
                    Grid.SetRow(rectangle, row);

                    //criar label
                    label = new Label();
                    label.Name = "PART_ServiceName_" + row.ToString();
                    label.HorizontalAlignment = _partLabel.HorizontalAlignment;
                    label.VerticalAlignment = _partLabel.VerticalAlignment;
                    label.SetResourceReference(Label.StyleProperty, "LabelFontLeft");
                    label.Height = _partLabel.Height;
                    label.Content = productId;
                    //deslocar a esquerda o conteudo
                    label.Margin = new System.Windows.Thickness(25, 0, 0, 0);
                    Grid.SetColumn(label, 0);
                    Grid.SetRow(label, row);

                    //criar botao
                    button = new StartStopButton();
                    button.Tag = productId;
                    button.IsChecked = runningProducts.Contains(productId);
                    button.Name = "PART_ToggleButton_" + row.ToString();
                    button.SetResourceReference(Button.StyleProperty, "ButtonActive");
                    button.Width = _partButton.Width;
                    button.Clicked += new StartStopButton.ClickedEventHandler(button_Clicked);
                    Grid.SetColumn(button, 1);
                    Grid.SetRow(button, row);

                    //adicionar itens no grid
                    content.Children.Add(rectangle);
                    content.Children.Add(label);
                    content.Children.Add(button);

                    //adicionar ao discionaro de produtos x controles
                    this.ProductsControls.Add(productId, button);

                    //criar um BackGroundworker para cada produto e adicionar no dicionario de produtos x workers
                    BackgroundWorker worker = new BackgroundWorker();
                    worker.DoWork += new DoWorkEventHandler(_bgWorker_DoWork);
                    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_bgWorker_RunWorkerCompleted);
                    this._productsWorkers.Add(productId, worker);

                    row++;
                }
            }
        }


        void button_Clicked(StartStopButton sender, ClickedEventArgs args)
        {
            string product = Convert.ToString(sender.Tag);
            if (!_partButton.IsChecked)
            {
                ConfigurationMessageBox.Show(string.Format("A instância '{0}' do serviço '{1}' não pode ser iniciada pois o serviço não está em execução.", product, Convert.ToString(_partLabel.Content)), ConfigurationMessageBoxButton.Ok, ConfigurationMessageBoxImage.Exclamation);
                return;
            }

            List<object> objects = new List<object>() { this.ProductsControls[product].IsChecked };
            this._productsWorkers[product].RunWorkerAsync(objects);
            this.ProductsControls[product].IsProcessing = true;
        }

        protected override void ServiceStoped()
        {
            base.ServiceStoped();

            if (this.ProductsControls != null)
            {
                foreach (KeyValuePair<string, StartStopButton> item in this.ProductsControls)
                {
                    item.Value.IsChecked = false;
                }
            }
        }

        protected override void ServiceStarted()
        {
            base.ServiceStarted();

            List<string> runningProducts = this.GetRunningProducts();

            foreach (KeyValuePair<string, StartStopButton> item in this.ProductsControls)
            {
                item.Value.IsChecked = runningProducts.Contains(item.Key);
            }
        }

        protected abstract bool StartProduct(string product);
        protected abstract bool StopProduct(string product);
        protected abstract List<string> GetConfiguredProducts();
        protected abstract List<string> GetRunningProducts();

    }
}
